package cn.cosmosx.base.util.codec;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NameCoder;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * XStream 实现bean与xml之间相互转换
 */
public class XStreamXmlBeanUtil {
    public final static String DEFAULT_CHARSET = "UTF-8";
    final static String XML_HEAD = "<?xml version=\"1.0\" encoding=\"%s\" standalone=\"yes\"?>" + System.getProperty("line.separator", "\n");

    /**
     * JavaBean转XML
     *
     * @param bean - JavaBean
     * @return - XML
     */
    public static String toXml(Object bean) {
        return toXml(bean, DEFAULT_CHARSET);
    }

    /**
     * JavaBean转XML
     *
     * @param bean    - JavaBean
     * @param charset - 编码
     * @return - XML
     */
    public static String toXml(Object bean, String charset) {
        final String cs = charset == null ? DEFAULT_CHARSET : charset;
        return String.format(XML_HEAD, cs) + initXStream(bean.getClass()).toXML(bean);
    }

    /**
     * XML转JavaBean
     *
     * @param xml       - XML
     * @param beanClazz - JavaBean Class
     * @param <T>
     * @return - JavaBean
     */
    @SuppressWarnings("unchecked")
    public static <T> T fromXml(String xml, Class<T> beanClazz) {
        return (T) initXStream(beanClazz).fromXML(xml);
    }

    private static XStream initXStream(Class<?> beanClazz) {
        // 单下划线转双下划线问题
        final NameCoder nameCoder = new XmlFriendlyNameCoder("-_", "_");
        XStream x = new XStream(new XppDriver(nameCoder));
        //不使用默认的类加载器，需要手动设置类加载器
        x.setClassLoader(beanClazz.getClassLoader());
        x.processAnnotations(beanClazz);
        x.allowTypesByRegExp(new String[]{".*"});
        // 开起注解功能
        x.autodetectAnnotations(true);
        // 忽律未知字段
        x.ignoreUnknownElements();
        return x;
    }
}